
/**
 * @static Archetype.Definitions.Joiner
 * Joiner is a way to wait for several Asynchronous events and then send a Callback
 */
$N("Archetype.Definitions.Joiner",{
    /**
     * Creates a new Joiner
     * @param {Array of String} keys to identify
     * @param {Function} callback
     * @param {Boolean} [debug] optional verbose logging
     */
    initialize: function(keys, callback, debug) {
        if(keys && keys.length === 0) {
            callback();
            return;
        }
        this.keys = $H();
        this.options = $H();
        this.debug = debug|Archetype.debugJoiner;
        $A(keys).each(function(key) {
            var addition = $H();
            addition.set(key, false);
            this.keys.update(addition);
        }.bind(this));
        this.callback = callback;
    },
    getJoiner: function(key, newOptions){
        if(this.debug) {
            Logger.debug("JOINER : key=" + key + ", options=", newOptions);
        }
        return function(key, newOptions) {
            this.keys.set(key, true);
            this.options.update($H(newOptions));
            var allFinished = true;
            this.keys.values().each(function(result) {
                allFinished = allFinished && result;
            });
            if(allFinished) {
                if(this.debug) {
                    Logger.debug("JOINER : callback keys=", this.keys);
                }
                this.callback(this.options);
                return true;
            } else {
                return false;
            }
        }.bind(this, key, newOptions);
    }
});

/** @static Archetype.Definitions.LoadJoiner */
$N("Archetype.Definitions.LoadJoiner", {
    /**
     * Creates a new Joiner
     * @param {Array of String} keys to identify
     * @param {Function} callback
     * @param {Boolean} [debug] optional verbose logging
     */
    initialize: function(type, keys, callback, debug) {
        //keys = keys.collect(function(key) {return $$U($U(key));});

        this.__super__.initialize.bind(this)(keys, callback, debug);

        $A(keys).each(function(key) {
            if(this.debug) {
                Logger.debug("JOINER : add listener key=" + key);
            }

            var eventListener = function(data) {
            	//Logger.warn("listener", key, arguments);
				if(/*event.event_data.*/data == key) {
                    if(this.debug) {
                        Logger.debug("JOINER : event key=" + /*event.event_data.*/data);
                    }
                    //Archetype.Events.removeEventListener(type, eventListener);
                    Archetype.engine.stopObserving(type, eventListener);
                    this.getJoiner(/*event.event_data.*/data)();
                }
            }.bind(this);

            //Archetype.Events.addEventListener(type, eventListener);
            Archetype.engine.observe(type, eventListener);
        }.bind(this));
    }
});

Archetype.Joiner = Archetype.Class.create(Archetype.Definitions.Joiner);
Archetype.LoadJoiner = Archetype.Class.create(Archetype.Definitions.Joiner).extend(Archetype.Definitions.LoadJoiner);
